//
//  PhotoBrowserCell.swift
//  SinaWeibo
//
//  Created by 小果 on 16/2/29.
//  Copyright © 2016年 小果. All rights reserved.
//

import UIKit
import SDWebImage
import SVProgressHUD

/// 照片 Cell 的 协议
protocol PhotoBrowserCellDelegate: NSObjectProtocol {
    /// 告诉控制器被缩放的比例
    func photoBrowserCellDidZooming(scale: CGFloat)
    /// 告诉控制器缩放完成
    func photoBrowserCellEndZoom()
}


/// 浏览图片cell，负责显示单张图片
class PhotoBrowserCell: UICollectionViewCell {
    /// 照片缩放的代理
    weak var photoDelegate: PhotoBrowserCellDelegate?
    // 图像的url 
    var url: NSURL? {
        didSet {
            // 重置scrollView的内容属性
            resetScrollView()
            
            // 打开菊花指示器
            indicator.startAnimating()
            imageView.image = nil
            // 对于SDWebImage,如果设置了image URL，图片不会出现重用；因为SDWebImage一旦设置url和之前的url不一致，会自动将image设置为nil
            
            // dispatch_time:从什么时候开始，要持续多久
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0 * NSEC_PER_SEC)), dispatch_get_main_queue()) {
                
                // RetryFailed:失败后可以允许重新加载
                // RefreshCached:如果服务器的图像发生变化，而本地的图像还是以前的图像，但是用此选项会更新服务器的图片
                // 使用GET方法能够缓存，如果服务器返回的是304，标识内容没有变化
                // 提交请求，如果是304，就是用本地缓存，否则使用服务器返回的图片
                self.imageView.sd_setImageWithURL(self.url, placeholderImage: nil, options: [SDWebImageOptions.RetryFailed, SDWebImageOptions.RefreshCached]) { (image, error, _, _) in
                    
                    // 关闭指示器
                    self.indicator.stopAnimating()
                    
                    // 判断图片是否下载完成
                    if error != nil {
                        SVProgressHUD.showInfoWithStatus("亲，您的网络好像不给力哦...")
                        return
                    }
                    
                    // 执行到此处，说明图片已经下载完成
                    self.setImagePositon()
                }
            }
        }
    }
    
    /// 重置 scrollView 的内容属性，因为缩放会影响到内容属性
    private func resetScrollView() {
        scrollView.contentSize = CGSizeZero
        scrollView.contentInset = UIEdgeInsetsZero
        scrollView.contentOffset = CGPointZero
        
        // 重新设置 imageView 形变属性
        imageView.transform = CGAffineTransformIdentity
    }

    
    // 设置图像的位置
    /**
        如果查看的图片缩放后没有屏幕高，就让其显示在屏幕的中央位置，否则显示在顶部，并设置 contentSize 可以滚动
    */
    private func setImagePositon() {
        let size = self.displaySize(imageView.image!)
        imageView.frame = CGRect(origin: CGPointZero, size: size)
        if size.height < scrollView.bounds.height {
            // 短图
            let y = (scrollView.bounds.height - size.height) * 0.5

            // 设置边距的好处是在缩放之后，能够自动调整contentSize，能够保证滚动看到边界
            scrollView.contentInset = UIEdgeInsets(top: y, left: 0, bottom: 0, right: 0)
        }else { // 长图
         
            scrollView.contentSize = size
        }
    }
    
    // 按照scrollView的宽度，计算缩放后的比例
    private func displaySize(image: UIImage) -> CGSize {
        
        // 1、计算图片的宽高比
        let scale = image.size.height / image.size.width
        // 2、计算高度
        let w = scrollView.bounds.width
        let h = w * scale
        
        return CGSize(width: w, height: h)
        
    }
    
 // MARK: - 构造函数，因为和屏幕一样大，只会被调用两次，后面如果在滚动就直接调用缓冲池中的cel
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        // 设置界面
        setupUI()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    // MARK: - 设置界面
    private func setupUI() {
        // 1、添加控件
        contentView.addSubview(scrollView)
        scrollView.addSubview(imageView)
        contentView.addSubview(indicator)
        
        // 2、设置位置(让scrollView的大小和cell一样大)
        var rect = bounds
        rect.size.width -= 20
        scrollView.frame = rect
        indicator.center = scrollView.center
        
        prepareScrollView()
        
    }
    
    // 设置ScrollView的缩放
    private func prepareScrollView() {
        // 1、设置代理
        scrollView.delegate = self
        
        // 2、设置图片的最大和最小的缩放比例
        scrollView.minimumZoomScale = 0.5
        scrollView.maximumZoomScale = 2.0
    }
    
    // MARK: - 懒加载控件
    /// 缩放图片
    private lazy var scrollView = UIScrollView()
    ///  显示单张图片
    lazy var imageView: UIImageView = {
        
        let iv = UIImageView()
        
        iv.contentMode = UIViewContentMode.ScaleAspectFill
        iv.clipsToBounds = true
        
        return iv
    }()
    /// 菊花
    private lazy var indicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
    
    
}

// MARK: - scrollView的代理方法
extension PhotoBrowserCell: UIScrollViewDelegate {
    // 1、告诉ScrollView要对那个图片进行缩放
    func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
        return imageView
    }
    ///  在图片缩放完成后会被调用
    ///
    ///  - parameter scrollView: scrollView
    ///  - parameter view:       view 被缩放的视图
    ///  - parameter scale:      scale 缩放完成后的比例
    func scrollViewDidEndZooming(scrollView: UIScrollView, withView view: UIView?, atScale scale: CGFloat) {
        
        // 1、调整y值
        var offsetY = (scrollView.bounds.height - imageView.frame.height) * 0.5
        // 2、调整X值
        var offsetX = (scrollView.bounds.width - imageView.frame.width) * 0.5
        // 3、调整offsetY，当offsetY < 0 时，顶部内容看不到
        offsetY = (offsetY < 0) ? 0 : offsetY
        offsetX = (offsetX < 0) ? 0 : offsetX
        // 4、重新设置间距
        scrollView.contentInset = UIEdgeInsets(top: offsetY, left: offsetX, bottom: 0, right: 0)
        
        // 通知代理缩放完成
        photoDelegate?.photoBrowserCellEndZoom()
        
    }
    ///  只要缩放就会被调用
    ///
    ///  - parameter scrollView: scrollView 
    /// 对形变参数的解析：
    /// 1、a / d 决定缩放的比例
    /// 2、tx / ty 决定位移
    /// 3、a b c d 共同决定旋转的角度
    /// 在修改形变的过程中，bounds的数值不会发生任何的变化,但是frame的数值会发生变化(bounds * transform => frame)
    func scrollViewDidZoom(scrollView: UIScrollView) {
        // 通知代理缩放比例
        photoDelegate?.photoBrowserCellDidZooming(imageView.transform.a)
    }
    
}

